package com.rickpan.service;

import org.springframework.core.io.Resource;

import java.io.*;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;

/**
 * 部分文件资源类
 * 用于支持HTTP Range请求，实现视频流媒体分段传输
 * 
 * @author RickPan Team
 * @since 2025-07-02
 */
public class PartialFileResource implements Resource {

    private final File file;
    private final long start;
    private final long contentLength;

    public PartialFileResource(File file, long start, long contentLength) {
        this.file = file;
        this.start = start;
        this.contentLength = contentLength;
    }

    @Override
    public boolean exists() {
        return file.exists();
    }

    @Override
    public boolean isReadable() {
        return file.canRead();
    }

    @Override
    public boolean isOpen() {
        return false;
    }

    @Override
    public boolean isFile() {
        return true;
    }

    @Override
    public URL getURL() throws IOException {
        return file.toURI().toURL();
    }

    @Override
    public URI getURI() throws IOException {
        return file.toURI();
    }

    @Override
    public File getFile() throws IOException {
        return file;
    }

    @Override
    public ReadableByteChannel readableChannel() throws IOException {
        FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel();
        return fileChannel.position(start);
    }

    @Override
    public long contentLength() throws IOException {
        return contentLength;
    }

    @Override
    public long lastModified() throws IOException {
        return file.lastModified();
    }

    @Override
    public Resource createRelative(String relativePath) throws IOException {
        throw new UnsupportedOperationException("PartialFileResource does not support createRelative");
    }

    @Override
    public String getFilename() {
        return file.getName();
    }

    @Override
    public String getDescription() {
        return "Partial file resource [" + file.getAbsolutePath() + "] (start=" + start + ", length=" + contentLength + ")";
    }

    @Override
    public InputStream getInputStream() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
        randomAccessFile.seek(start);
        
        return new InputStream() {
            private long bytesRead = 0;
            
            @Override
            public int read() throws IOException {
                if (bytesRead >= contentLength) {
                    return -1;
                }
                bytesRead++;
                return randomAccessFile.read();
            }
            
            @Override
            public int read(byte[] b, int off, int len) throws IOException {
                if (bytesRead >= contentLength) {
                    return -1;
                }
                
                long remainingBytes = contentLength - bytesRead;
                int bytesToRead = (int) Math.min(len, remainingBytes);
                
                int actualBytesRead = randomAccessFile.read(b, off, bytesToRead);
                if (actualBytesRead > 0) {
                    bytesRead += actualBytesRead;
                }
                
                return actualBytesRead;
            }
            
            @Override
            public void close() throws IOException {
                randomAccessFile.close();
            }
        };
    }
}
